# 全局异常处理器

from fastapi import Request, HTTPException
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
from starlette.exceptions import HTTPException as StarletteHTTPException
import logging
from typing import Union

from src.utils.http_base import HttpResp

# 获取日志记录器
logger = logging.getLogger(__name__)


class CustomException(Exception):
    """自定义异常基类"""
    def __init__(self, code: int, message: str, detail: str = None):
        self.code = code
        self.message = message
        self.detail = detail
        super().__init__(self.message)


class BusinessException(CustomException):
    """业务异常"""
    def __init__(self, message: str, detail: str = None):
        super().__init__(HttpResp.FAILED.code, message, detail)


class AuthenticationException(CustomException):
    """认证异常"""
    def __init__(self, message: str = "认证失败", detail: str = None):
        super().__init__(HttpResp.TOKEN_INVALID.code, message, detail)


class AuthorizationException(CustomException):
    """授权异常"""
    def __init__(self, message: str = "权限不足", detail: str = None):
        super().__init__(HttpResp.NO_PERMISSION.code, message, detail)


class ValidationException(CustomException):
    """验证异常"""
    def __init__(self, message: str = "参数验证失败", detail: str = None):
        super().__init__(HttpResp.PARAMS_VALID_ERROR.code, message, detail)


async def custom_exception_handler(request: Request, exc: CustomException):
    """自定义异常处理器"""
    logger.error(f"Custom exception: {exc.message}, detail: {exc.detail}")
    return JSONResponse(
        status_code=200,  # 统一返回200，通过code字段区分错误
        content={
            "code": exc.code,
            "message": exc.message,
            "data": None,
            "detail": exc.detail
        }
    )


async def http_exception_handler(request: Request, exc: Union[HTTPException, StarletteHTTPException]):
    """HTTP异常处理器"""
    logger.error(f"HTTP exception: {exc.status_code} - {exc.detail}")
    
    # 根据HTTP状态码映射到自定义错误码
    if exc.status_code == 404:
        code = HttpResp.REQUEST_404_ERROR.code
        message = HttpResp.REQUEST_404_ERROR.message
    elif exc.status_code == 405:
        code = HttpResp.REQUEST_METHOD_ERROR.code
        message = HttpResp.REQUEST_METHOD_ERROR.message
    elif exc.status_code == 401:
        code = HttpResp.TOKEN_INVALID.code
        message = HttpResp.TOKEN_INVALID.message
    elif exc.status_code == 403:
        code = HttpResp.NO_PERMISSION.code
        message = HttpResp.NO_PERMISSION.message
    else:
        code = HttpResp.SYSTEM_ERROR.code
        message = HttpResp.SYSTEM_ERROR.message
    
    return JSONResponse(
        status_code=200,
        content={
            "code": code,
            "message": message,
            "data": None,
            "detail": str(exc.detail)
        }
    )


async def validation_exception_handler(request: Request, exc: RequestValidationError):
    """参数验证异常处理器"""
    logger.error(f"Validation exception: {exc.errors()}")
    
    # 格式化验证错误信息
    error_details = []
    for error in exc.errors():
        field = ".".join(str(loc) for loc in error["loc"])
        error_details.append(f"{field}: {error['msg']}")
    
    return JSONResponse(
        status_code=200,
        content={
            "code": HttpResp.PARAMS_VALID_ERROR.code,
            "message": HttpResp.PARAMS_VALID_ERROR.message,
            "data": None,
            "detail": "; ".join(error_details)
        }
    )


async def general_exception_handler(request: Request, exc: Exception):
    """通用异常处理器"""
    logger.error(f"Unexpected exception: {type(exc).__name__} - {str(exc)}", exc_info=True)
    
    return JSONResponse(
        status_code=200,
        content={
            "code": HttpResp.SYSTEM_ERROR.code,
            "message": HttpResp.SYSTEM_ERROR.message,
            "data": None,
            "detail": "服务器内部错误，请稍后重试"
        }
    )